/* Copyright Paul Reiche, Fred Ford. 1992-2002, Christopher Night 2013

This file is part of the HTML5 port of Ur-Quan Masters (UQM-HTML5)

UQM-HTML5 is free software: you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

UQM-HTML5 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Public License for more details.

You should have received a copy of the GNU General Public License along with this program.  If not,
see <http://www.gnu.org/licenses/>. */

// Heavily adapted from src/uqm/ship.c


var MAX_ALLOWED_SPEED = 18

// Ship constructor
// The element responsible for the ship while in combat
function Ship(race) {
	this.race = race
	this.info = this.race.ship_info
	this.input_state = {}
	this.current = {}
	this.next = {}
	this.parent = this
	this.mass = this.info.mass
	this.crew_level = this.info.max_crew
}
Ship.prototype = {
	// Join the battle
	spawn: function () {
		this.energy_counter = 0
		this.weapon_counter = 0
		this.special_counter = 0
		this.turn_wait = 0
		this.thrust_wait = 0
		this.energy_level = this.info.max_energy
		this.life_span = 1   // NORMAL_LIFE
		this.colorCycleIndex = 0
		this.status = {}
		this.old_status = {}
		this.state = {
			APPEARING: true,
			PLAYER_SHIP: true,
			IGNORE_SIMILAR: true,
		}
		this.facing = 0
		if (!this.info.frames) this.info.frames = graphics.getfarray(this.info.farrayname)
		this.current = {
			x: Math.random() * ARENA_WIDTH,
			y: Math.random() * ARENA_HEIGHT,
			frame: this.info.frames[this.facing]
		}
		this.vx = 0
		this.vy = 0
		elements.push(this)
	},
	preprocess_func: function () {
		this.race.regenerate_energy.apply(this)
		this.race.preprocess_func.apply(this)
		this.race.turn_func.apply(this)
		this.race.thrust_func.apply(this)
	},
	postprocess_func: function () {
		if (!this.crew_level) return
		this.race.weapon_func.apply(this)
		this.race.special_func.apply(this)
		this.race.postprocess_func.apply(this)
	},
	
	
	// Apply thruster
	inertial_thrust: function () {
		var thrust_increment = this.info.thrust_increment / 4
		var max_thrust = this.info.max_thrust / 4
		var Aface = this.facing / 16 * tau
		var Acurrent = Math.atan2(this.vx, this.vy)
		var maxed = this.status.SHIP_AT_MAX_SPEED || this.status.SHIP_BEYOND_MAX_SPEED
		this.status.SHIP_AT_MAX_SPEED = false
		this.status.SHIP_BEYOND_MAX_SPEED = false
		if (thrust_increment == max_thrust) {  // inertia-less acceleration
			this.vx = Math.cos(Aface) * max_thrust
			this.vy = Math.sin(Aface) * max_thrust
			this.status.SHIP_AT_MAX_SPEED = true
		} else if (Aface == Acurrent && maxed && !this.status.SHIP_IN_GRAVITY_WELL) {
			// TODO: there should be some leeway here between Aface and Acurrent.
			this.status.SHIP_AT_MAX_SPEED = true
			this.status.SHIP_BEYOND_MAX_SPEED = true
		} else {
			var v = Math.sqrt(this.vx * this.vx + this.vy * this.vy)
			var vx = this.vx + Math.sin(Aface) * thrust_increment
			var vy = this.vy + Math.cos(Aface) * thrust_increment
			var vnew = Math.sqrt(vx * vx + vy * vy)
			if (vnew < max_thrust) {
				this.vx = vx
				this.vy = vy
			} else if (vnew < v || (this.status.SHIP_IN_GRAVITY_WELL && vnew < MAX_ALLOWED_SPEED)) {
				this.vx = vx
				this.vy = vy
				this.status.SHIP_AT_MAX_SPEED = true
				this.status.SHIP_BEYOND_MAX_SPEED = true
			} else {
				this.vx = max_thrust * vx / vnew
				this.vy = max_thrust * vy / vnew
				this.status.SHIP_AT_MAX_SPEED = true
				this.status.SHIP_BEYOND_MAX_SPEED = true
			}
		}
		this.status.SHIP_IN_GRAVITY_WELL = false
	},

	collision_func: function (telement) {
		// TODO: take damage if telement is a planet
	},
	
	// From uqm/tactrans.c
	spawn_ion_trail: function () {
		var ion = new Ion(this)
		elements.unshift(ion)
	},
	
}


function Ion(ship) {
	this.parent = ship
	this.playerNr = ship.playerNr
	this.state = {
		APPEARING: true,
		FINITE_LIFE: true,
		NONSOLID: true,
		PRE_PROCESS: true,
		SKIP_COLLISION: true,
	}
	// The element "dies" several times, changing color
	this.colorCycleIndex = 0
	this.color_span = 1
	this.life_span = this.color_span - 1
	var h = ship.info.frames[0].img.height / 2
	var A = ship.facing * tau / 16
	this.current = {
		x: ship.current.x - h * Math.sin(A),
		y: ship.current.y - h * Math.cos(A),
		frame: this.colors[this.colorCycleIndex],
	}
}
Ion.prototype = {
	colors: ("#f8a800 #f88800 #f87000 #f85000 #f83800 #f81800 #f80000 " +
		"#d80000 #b80000 #980000 #780000 #580000").split(" "),
	death_func: function () {
		++this.colorCycleIndex
		if (this.colorCycleIndex >= this.colors.length) return
		this.life_span = this.color_span
		this.next.frame = this.colors[this.colorCycleIndex]
		this.state.DISAPPEARING = false
	},
}


var ship = {
	// This doesn't really seem to belong in this module but here it is.
	animation_preprocess: function () {
		if (this.turn_wait > 0) {
			--this.turn_wait
		} else {
			this.frame_index = (this.frame_index + 1) % this.farray.length
			this.next.frame = this.farray[this.frame_index]
			this.turn_wait = this.next_turn
		}
	},
}



